﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.OData.Query;

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Driver.Linq;

using Inovout.Cloud.DataStore.Common;
using Inovout.Cloud.DataStore.Models;
using MongoDB.Bson.Serialization.Attributes;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData;

namespace Inovout.Cloud.DataStore.Utility
{
    /// <summary>
    /// 参考地址：
    /// 
    /// OData:
    /// http://www.odata.org/documentation/odata-version-2-0/uri-conventions/
    /// 
    /// 
    /// http://docs.mongodb.org/ecosystem/tutorial/use-csharp-driver/
    /// http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-csharp-driver/
    /// http://docs.mongodb.org/ecosystem/tutorial/use-linq-queries-with-csharp-driver/
    /// http://www.cnblogs.com/Johnzhang/p/3314178.html
    /// http://database.51cto.com/art/201007/212039.htm
    /// http://www.cnblogs.com/qq75077027/archive/2012/12/26.html
    /// http://www.cnblogs.com/snowdream/archive/2008/07/18/1246308.html
    /// https://dynamiclinq.codeplex.com/documentation
    /// http://www.cnblogs.com/flysnow-z/archive/2009/06/16/1504338.html
    /// http://ecs.syr.edu/faculty/fawcett/handouts/CoreTechnologies/CSharp/samples/CSharpSamples/LinqSamples/DynamicQuery/Dynamic%20Expressions.html
    /// 
    /// http://www.cnblogs.com/xumingxiang/archive/2012/04/08/2437468.html#title9
    /// 
    /// 
    /// http://stackoverflow.com/questions/4615916/sql-query-to-mongodb
    /// http://www.querymongo.com/
    /// http://klaus.dk/sqltomongodb/
    /// http://hibernate.org/ogm/
    /// (The power and simplicity of JPA for NoSQL datastores.)
    /// http://en.wikipedia.org/wiki/Java_Persistence_Query_Language
    /// 
    /// http://rickosborne.org/blog/2010/02/playing-around-with-mongodb-and-mapreduce-functions/
    /// http://docs.mongodb.org/manual/reference/database-references/
    /// 
    /// 
    /// 
    /// http://dev.scottw.com/mongodb-dynamics
    /// https://app.box.com/shared/knqqd9jn9k
    /// http://inspectorit.com/tips-tricks/when-does-the-mongo-c-driver-get-data/
    /// (多表Join)
    /// </summary>
    public class MongoDbClient
    {
        #region 变量定义
        //Mongo服务器
        private MongoServer dbServer = null;
        #endregion

        #region 构造函数
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serverConnectionString">服务器连接字符串</param>
        public MongoDbClient(string serverConnectionString)
        {
            //连接数据服务器最简单的方法使用连接字符串。标准格式如下
            //mongodb://[username:password@]hostname[:port][/[database][?options]]  

            //如果你要连接一个需要认证的服务器username和password是必须有的。端口默认为27017。
            //当需要连接多个服务器时需要用逗号隔开。写法如下
            //mongodb://server1,server2:27017,server2:27018

            try
            {
                if (!String.IsNullOrEmpty(serverConnectionString))
                {
                    MongoServer dbServer = new MongoClient(serverConnectionString).GetServer();
                    //MongoServer dbServer = MongoServer.Create(serverConnectionString);
                    this.dbServer = dbServer;
                }
            }
            catch (Exception ex)
            {
                this.dbServer = null;
                throw ex;//如果此处抛异常，查明原因，不要随便不处理ex;
            }
        }
        #endregion

        #region 服务器相关操作

        public static MongoServer CreateServer(string serverConnectionString)
        {
            try
            {
                //MongoServer dbServer = MongoServer.Create(serverConnectionString);

                MongoServer dbServer = new MongoClient(serverConnectionString).GetServer();
                if (dbServer.State != MongoServerState.Connected)
                {
                    dbServer.Connect();
                }
                return dbServer;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 连接Mongo DB 服务器
        /// </summary>
        public void Connect()
        {
            try
            {
                if (this.dbServer.State != MongoServerState.Connected)
                {
                    this.dbServer.Connect();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 连接Mongo DB 服务器
        /// </summary>
        /// <param name="timeSpan">指定连接超时时间</param>
        public void Connect(TimeSpan timeSpan)
        {
            try
            {
                if (this.dbServer.State != MongoServerState.Connected)
                {
                    this.dbServer.Connect(timeSpan);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 连接Mongo DB 服务器
        /// </summary>
        public void ReConnect()
        {
            try
            {
                this.dbServer.Reconnect();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 断开与Mongo DB服务器之间的连接
        /// </summary>
        public void Disconnect()
        {
            try
            {
                this.dbServer.Disconnect();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 关闭MongoDB服务器
        /// </summary>
        public void Shutdown()
        {
            try
            {
                this.dbServer.Shutdown();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 数据库的相关操作

        /// <summary>
        /// 创建数据库
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns></returns>
        public MongoDatabase CreateDatabase(string databaseName)
        {
            try
            {
                return this.dbServer.GetDatabase(databaseName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 根据数据库名取得某一个数据库对象
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns></returns>
        public MongoDatabase GetDatabase(string databaseName)
        {
            try
            {
                return this.dbServer.GetDatabase(databaseName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得Mongo DB Server上的所有数据库名
        /// </summary>
        /// <returns></returns>
        public IEnumerable<string> GetDatabaseNames()
        {
            try
            {
                return this.dbServer.GetDatabaseNames();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得Mongo DB Server上的所有数据库
        /// </summary>
        /// <returns></returns>
        public IEnumerable<MongoDatabase> GetDatabases()
        {
            try
            {
                IEnumerable<string> dbNames = this.dbServer.GetDatabaseNames();
                if (dbNames == null || dbNames.ToList().Count == 0)
                {
                    return null;
                }

                List<MongoDatabase> databaseList = new List<MongoDatabase>();
                MongoDatabase database = null;
                foreach (string dbName in dbNames)
                {
                    database = this.dbServer.GetDatabase(dbName);
                    if (database != null)
                    {
                        databaseList.Add(database);
                    }
                }

                return databaseList;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 判断数据库是否存在
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns></returns>
        public bool DatabaseExists(string databaseName)
        {
            try
            {
                return this.dbServer.DatabaseExists(databaseName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除数据库
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns></returns>
        public bool DropDatabase(string databaseName)
        {
            try
            {
                CommandResult result = this.dbServer.DropDatabase(databaseName);
                return result.Ok;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 表的相关操作

        /// <summary>
        /// 创建表
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns>是否操作成功</returns>
        public bool CreateTable(string databaseName, string tableName)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName))
            {
                return false;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return false;
                }

                if (database.CollectionExists(tableName))
                {
                    return true;
                }

                CommandResult result = database.CreateCollection(tableName);
                return result.Ok;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除表
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns>是否操作成功</returns>
        public bool DropTable(string databaseName, string tableName)
        {
            if (String.IsNullOrEmpty(tableName))
            {
                return false;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return false;
                }

                return database.DropCollection(tableName).Ok;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得表
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns>表信息</returns>
        public MongoCollection GetTable(string databaseName, string tableName)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName))
            {
                return null;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }

                return database.GetCollection(tableName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得数据库中的所有表名
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns>所有表名</returns>
        public IEnumerable<string> GetTableNames(string databaseName)
        {
            if (String.IsNullOrEmpty(databaseName))
            {
                return null;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }

                return database.GetCollectionNames();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得数据库中的所有表
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns>所有表</returns>
        public IEnumerable<MongoCollection> GetTables(string databaseName)
        {
            if (String.IsNullOrEmpty(databaseName))
            {
                return null;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }

                IEnumerable<String> tableNames = database.GetCollectionNames();
                if (tableNames == null || tableNames.Count() == 0)
                {
                    return null;
                }

                List<MongoCollection> tableList = new List<MongoCollection>();
                MongoCollection table = null;
                foreach (String tableName in tableNames)
                {
                    table = database.GetCollection(tableName);
                    tableList.Add(table);
                }

                return tableList;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 判断表是否存在
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns>表是否存在</returns>
        public bool TableExists(string databaseName, string tableName)
        {
            if (GetTable(databaseName, tableName) == null)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 取得数据库的信息
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <returns>数据库的信息</returns>
        public DatabaseStatsResult GetDatabaseInfo(string databaseName)
        {
            if (String.IsNullOrEmpty(databaseName))
            {
                return null;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }

                return database.GetStats();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 重命名表
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="oldTableName">表的原始名称</param>
        /// <param name="newTableName">表的新名称</param>
        public bool RenameTable(string databaseName, string oldTableName, string newTableName)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(oldTableName) || String.IsNullOrEmpty(newTableName))
            {
                return false;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return false;
                }

                CommandResult result = database.RenameCollection(oldTableName, newTableName);
                return result.Ok;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得表的信息
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名称</param>
        /// <returns>表的信息</returns>
        public CollectionStatsResult GetTableInfo(string databaseName, string tableName)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName))
            {
                return null;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }

                MongoCollection table = database.GetCollection(tableName);
                if (table == null)
                {
                    return null;
                }

                return table.GetStats();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得表的数据量
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名称</param>
        /// <returns>表的数据量</returns>
        public long GetTotalDataSize(string databaseName, string tableName)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName))
            {
                return 0;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return 0;
                }

                MongoCollection table = database.GetCollection(tableName);
                if (table == null)
                {
                    return 0;
                }

                return table.GetTotalDataSize();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得表的存储空间
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名称</param>
        /// <returns>表的存储空间</returns>
        public long GetTotalStorageSize(string databaseName, string tableName)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName))
            {
                return 0;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return 0;
                }

                MongoCollection table = database.GetCollection(tableName);
                if (table == null)
                {
                    return 0;
                }

                return table.GetTotalStorageSize();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 表的记录的相关操作

        /// <summary>
        /// 取得表的所有记录数
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns>表的所有记录数</returns>
        public int GetEntityCount(string databaseName, string tableName)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return 0;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return 0;
                }

                return table.FindAll().AsQueryable().Count();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public long GetCount(string databaseName, string tableName)
        {
            try
            {
                long count = 0;
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return 0;
                }
                count = database.GetCollection(tableName).Count();
                return count;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得表的所有记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="tableEntityType">表对应的结构类型</param>
        /// <returns>表的所有记录</returns>
        public IQueryable FindAllEntities(string databaseName, string tableName, Type tableEntityType)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }

                var table = database.GetCollection(tableEntityType, tableName);
                if (table == null)
                {
                    return null;
                }


                //重新构造MongoDb的AsQueryable方法
                var query = AsQueryable(table, tableEntityType);
                return query;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取得表的记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns>表的记录</returns>
        public BsonDocument FindOneByObjectId(string databaseName, string tableName, string primaryKey)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return null;
                }
                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return null;
                }
               //var entity = table.FindOneById(primaryKey);
                 var entity = table.FindOne(Query.EQ(Constant.ObjectId, primaryKey));
                return entity;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 插入新记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="entity">记录</param>
        public void InsertEntity(string databaseName, string tableName, Dictionary<String, Object> entity)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName) ||
                entity == null || entity.Count == 0)
            {
                return;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                if (!entity.ContainsKey(Constant.ObjectId))
                {
                    entity.Add(Constant.ObjectId, Guid.NewGuid().ToString().ToLower());
                }
                BsonDocument document = new BsonDocument(entity);

                //插入记录
                table.Insert(document);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 批量插入记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="entities">记录集合</param>
        public void InsertEntitiesBatch(string databaseName, string tableName, List<Dictionary<String, Object>> entities)
        {
            if (String.IsNullOrEmpty(databaseName) || String.IsNullOrEmpty(tableName) ||
                entities == null || entities.Count == 0)
            {
                return;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                BsonDocument[] documents = new BsonDocument[entities.Count];
                for (int i = 0; i < entities.Count; i++)
                {
                    if (!entities[i].ContainsKey(Constant.ObjectId))
                    {
                        entities[i].Add(Constant.ObjectId, Guid.NewGuid().ToString().ToLower());
                    }
                    documents[i] = new BsonDocument(entities[i]);
                }

                //批量插入记录
                //同时插入多条记录时记录时，InsertBatch()方法比Insert()效率要高，特别是在安全模式下
                table.InsertBatch(documents);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 更新记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKey">被更新记录的主键</param>
        /// <param name="entity">更新后的对象结果</param>
        public void UpdateEntity(string databaseName, string tableName, string primaryKey, Dictionary<String, Object> newEntity)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                var query = Query.EQ(Constant.ObjectId, primaryKey);
                var update = new UpdateDocument(newEntity);

                //执行更新
                table.Update(query, update);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Save方法是Insert和Update方法的组合。
        /// 如果ID字段有值则假定该文档是存在的并保存所有更新，否则插入一条新的文档记录。
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="entity">新的记录结果</param>
        public void SaveEntity(string databaseName, string tableName, Dictionary<String, Object> entity)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                if (entity.ContainsKey(Constant.ObjectId))
                {
                    table.Save(new BsonDocument(entity));
                }
                else
                {
                    entity.Add(Constant.ObjectId, Guid.NewGuid().ToString().ToLower());
                    table.Insert(new BsonDocument(entity));
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// 批量保存记录集
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="tableName"></param>
        /// <param name="entities"></param>
        public void SaveEntities(string databaseName, string tableName, List<Dictionary<string, object>> entities)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                foreach (Dictionary<string, object> entity in entities)
                {
                    if (entity.ContainsKey(Constant.ObjectId))
                    {
                        table.Save(new BsonDocument(entity));
                    }
                    else
                    {
                        entity.Add(Constant.ObjectId, Guid.NewGuid().ToString().ToLower());
                        table.Insert(new BsonDocument(entity));
                    }
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKey">主键</param>
        public void RemoveEntity(string databaseName, string tableName, string primaryKey)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                //删除条件
                var query = Query.EQ(Constant.ObjectId, primaryKey);

                //执行删除
                table.Remove(query);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 根据条件删除
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="conditions">删除条件</param>
        public void RemoveEntities(string databaseName, string tableName, Dictionary<string, object> conditions)
        {

            if (conditions == null || conditions.Count == 0)
            {
                return;
            }

            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }


                IMongoQuery[] queries = new IMongoQuery[conditions.Count];
                int index = 0;
                foreach (KeyValuePair<string, object> kvp in conditions)
                {
                    queries[index] = getQuery(kvp.Key, kvp.Value);
                    index++;
                }

                IMongoQuery query = Query.And(queries);
                table.FindAndRemove(query, null);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除指定的列
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <param name="keyName">列名</param>
        public void RemoveField(string databaseName, string tableName, string keyName)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                MongoCursor<BsonDocument> allEntites = table.FindAll();
                foreach (BsonDocument entity in allEntites.AsEnumerable())
                {
                    if (entity.Contains(keyName))
                    {
                        entity.Remove(keyName);
                        table.Save(entity);
                    }
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除表的所有记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        public void RemoveAllEntities(string databaseName, string tableName)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                MongoCollection<BsonDocument> table = database.GetCollection<BsonDocument>(tableName);
                if (table == null)
                {
                    return;
                }

                //执行删除
                table.RemoveAll();

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除数据库的所有记录
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        public void RemoveAllEntities(string databaseName)
        {
            try
            {
                MongoDatabase database = this.dbServer.GetDatabase(databaseName);
                if (database == null)
                {
                    return;
                }

                IEnumerable<String> tableNames = database.GetCollectionNames();
                if (tableNames == null || tableNames.Count() == 0)
                {
                    return;
                }

                MongoCollection table = null;
                foreach (string tableName in tableNames)
                {
                    table = database.GetCollection(tableName);
                    if (table != null)
                    {
                        table.RemoveAll();
                    }
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 私有方法
        /// <summary>
        /// 取得所有列名
        /// </summary>
        /// <param name="select">列名（用","隔开）</param>
        /// <returns></returns>
        private string[] GetSelectFields(string select)
        {
            if (String.IsNullOrEmpty(select))
            {
                return null;
            }

            //去掉所有的空格
            select = select.Trim().Replace(Constant.Space, Constant.Empty);

            //取得所有列名
            string[] fields = select.Split(Constant.CommaChar);
            return fields;
        }

        private IMongoQuery getQuery(string keyName, object keyValue)
        {
            IMongoQuery query = null;
            string valueType = keyValue.GetType().Name;
            switch (valueType)
            {
                case "String":
                    query = Query.EQ(keyName, keyValue.ToString());
                    break;
                case "Int":
                    query = Query.EQ(keyName, (int)keyValue);
                    break;
                case "Int16":
                    query = Query.EQ(keyName, (Int16)keyValue);
                    break;
                case "Int32":
                    query = Query.EQ(keyName, (Int32)keyValue);
                    break;
                case "Int64":
                    query = Query.EQ(keyName, (Int64)keyValue);
                    break;
                case "Bool":
                    query = Query.EQ(keyName, (bool)keyValue);
                    break;
                case "Boolean":
                    query = Query.EQ(keyName, (bool)keyValue);
                    break;
                case "Double":
                    query = Query.EQ(keyName, (Double)keyValue);
                    break;
                case "DateTime":
                    query = Query.EQ(keyName, (DateTime)keyValue);
                    break;
                case "Guid":
                    query = Query.EQ(keyName, (Guid)keyValue);
                    break;
                default:
                    query = Query.EQ(keyName, keyValue.ToString());
                    break;
            }

            return query;
        }
        #endregion

        #region 其他方法
        /// <summary>
        /// 重新构造MongoDb的AsQueryable方法
        /// </summary>
        /// <param name="collection">MongoDb的表</param>
        /// <param name="type">表对应的动态类</param>
        /// <returns></returns>
        public static IQueryable AsQueryable(MongoCollection collection, Type type)
        {
            var provider = new MongoQueryProvider(collection);

            var collectionDefinition = typeof(MongoQueryable<>);
            var collectionType = collectionDefinition.MakeGenericType(type);
            var constructorInfo = collectionType.GetConstructor(new Type[] { typeof(MongoQueryProvider) });
            return (IQueryable)constructorInfo.Invoke(new object[] { provider });

        }
        #endregion

    }
}
